home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Freeware 1998 June
/
SGI Freeware 1998 June.iso
/
dist
/
fw_ATxgopher.idb
/
usr
/
freeware
/
src
/
xgopher.1.3
/
itemList.c.z
/
itemList.c
Wrap
C/C++ Source or Header
|
1998-01-21
|
8KB
|
426 lines
/* itemList.c
routines to manage the data structures for gopher items. */
/*---------------------------------------------------------------*/
/* Xgopher version 1.3 08 April 1993 */
/* version 1.2 20 November 1992 */
/* version 1.1 20 April 1992 */
/* version 1.0 04 March 1992 */
/* X window system client for the University of Minnesota */
/* Internet Gopher System. */
/* Allan Tuchman, University of Illinois at Urbana-Champaign */
/* Computing and Communications Services Office */
/* Copyright 1992, 1993 by */
/* the Board of Trustees of the University of Illinois */
/* Permission is granted to freely copy and redistribute this */
/* software with the copyright notice intact. */
/*---------------------------------------------------------------*/
#include <stdio.h>
#include "gopher.h"
#include "itemList.h"
#include "dir.h"
#include "listP.h"
#include "osdep.h"
static gopherItemList unusedItems = {NULL, NULL};
static int firstItemAlloc = TRUE;
#define FREE_ITEM_LIST_LENGTH itemListLength(&unusedItems)
/* Item list management routines:
initItemList(gopherItemListP) set list pointers to indicate empty
appendItem(gopherItemListP, gopherItemP) add item to end of list
getItemN(gopherItemListP, int) return pointer to Nth item in list
nextItem(gopherItemP) return pointer to next item in list
removeItemN(gopherItemListP, int) delete Nth item from a list
removeItem(gopherItemListP, gopherItemP) delete given item from a list
itemListLength(gopherItemListP) return length of item list
for internal use only:
pushItem(gopherItemListP, gopherItemP) push item to front of list
printItemList(gopherItemListP, char *) Only defined if DEBUG is
freeList management routines:
acquireItem() return ptr to a gopherItem structure
releaseItem(gopherItemP) Return a gopher item to the free list
freeItemList(gopherItemP) return list of items to the free list
freeList management routines (internal only):
allocGopherItem(int) allocate N new items
releaseItems(gopherItemP) Return items to the free list (internal)
*/
/* acquireItem
Allocate a gopher item from the free list */
gopherItemP
acquireItem()
{
gopherItemP gi;
if (unusedItems.first == NULL) {
/* out of gopher items. First reclaim those that
are out of date, then allocate more if necessary */
checkDirStack();
if (unusedItems.first == NULL ||
FREE_ITEM_LIST_LENGTH < itemIncrement) {
allocGopherItem(firstItemAlloc ?
itemStart : itemIncrement);
firstItemAlloc = FALSE;
}
}
gi = unusedItems.first;
unusedItems.first = gi->next;
if (unusedItems.first == NULL) unusedItems.last = NULL;
gi->next = NULL;
return gi;
}
/* initItemList
Set the list pointers to indicate that the list is empty */
void
initItemList(list)
gopherItemListP list;
{
list->first = list->last = NULL;
return;
}
/* releaseItem
Return a cleared out gopher item to the free list */
void
releaseItem(gi)
gopherItemP gi;
{
if (gi != NULL)
pushItem(&unusedItems, gi);
return;
}
/* releaseItems
Return a linked list of cleared out gopher items to the free list */
static void
releaseItems(gi)
gopherItemP gi;
{
gopherItemP p;
int n=0;
while (gi != NULL) {
p = gi->next;
releaseItem(gi);
n++;
gi = p;
}
#ifdef NOT_USED
/* this code is a more efficient way of doing the above */
if (gi == NULL) return;
/* set p to point to the end of the items */
for (p=gi; p->next != NULL; p=p->next) ;
if (unusedItems.last == NULL) unusedItems.last = p;
p->next = unusedItems.first;
unusedItems.first = gi;
#endif /* NOT_USED */
return;
}
/* freeItemList
Return a list of gopher items to the free list and clear the
list header */
void
freeItemList(list)
gopherItemListP list;
{
gopherItemP p;
int n=0;
if (list != NULL) {
/* if we know that they are already cleared out, we could use:
releaseItems(list->first);
but we don't, so free them one at a time. */
gopherItemP gi=list->first;
while (gi != NULL) {
p = gi->next;
freeItem(gi);
n++;
gi = p;
}
initItemList(list);
}
return;
}
/* itemListLength
return the number of items in an item list */
int
itemListLength(list)
gopherItemListP list;
{
int n;
gopherItemP p;
if (list == NULL) return 0;
for (n=0, p=list->first; p != NULL; n++, p=p->next) ;
return n;
}
/* appendItem
append an item to the end of an item list */
void
appendItem(list, gi)
gopherItemListP list;
gopherItemP gi;
{
if (list == NULL || gi == NULL) return;
if (list->last == NULL) {
list->first = list->last = gi;
} else {
list->last->next = gi;
list->last = gi;
}
gi->next = NULL;
return;
}
/* removeItemN
delete the Nth item from a list. The first item is numbered 0 */
void
removeItemN(list, n)
gopherItemListP list;
int n;
{
gopherItemP p, prev;
if (list == NULL) return;
if (n < 0) return;
if ((p = list->first) == NULL) return;
if (n == 0) {
list->first = p->next;
if (list->last == p) list->last = NULL;
freeItem(p);
} else {
for (prev=p, p=p->next; p!= NULL; prev=p, p=p->next) {
if (--n == 0) {
prev->next = p->next;
if (p == list->last) list->last = prev;
freeItem(p);
break;
}
}
}
return;
}
/* removeItem
delete the a given item from a list. */
void
removeItem(list, gi)
gopherItemListP list;
gopherItemP gi;
{
gopherItemP p, prev;
if (list == NULL) return;
if ((p = list->first) == NULL) return;
if (p == gi) {
list->first = p->next;
if (list->last == p) list->last = NULL;
freeItem(p);
} else {
for (prev=p, p=p->next; p!= NULL; prev=p, p=p->next) {
if (p == gi) {
prev->next = p->next;
if (p == list->last) list->last = prev;
freeItem(p);
break;
}
}
}
return;
}
/* getItemN
return a pointer to the Nth item of the specified item list,
starting with number 0 */
gopherItemP
getItemN(list, n)
gopherItemListP list;
int n;
{
gopherItemP p;
if (n < 0) return NULL;
if (list == NULL) return NULL;
p = list->first;
for ( ; p != NULL; p=p->next) {
if (n-- == 0) break;
}
return p;
}
/* nextItem
return a pointer to the next item in a list, given an existing item. */
gopherItemP
nextItem(gi)
gopherItemP gi;
{
if (gi == NULL) return NULL;
return gi->next;
}
/* pushItem
push an item onto the front of a item list */
static void
pushItem(list, gi)
gopherItemListP list;
gopherItemP gi;
{
gi->next = list->first;
list->first = gi;
if (list->last == NULL) list->last = gi;
return;
}
/* allocGopherItem
Allocate n new gopher items, adding them to the free list */
static void
allocGopherItem(n)
int n;
{
gopherItemP gil, p;
int i;
if (n <= 0) return;
if ((gil = (gopherItemP) malloc(n * sizeof(gopherItem))) == NULL) {
/* out of memory */
fprintf (stderr, "There is not enough memory to continue.\n");
exit(3);
}
for (i=0, p=gil; i<n-1; i++, p++) {
initItemFields(p);
p->next = p+1;
}
initItemFields(p);
p->next = NULL;
releaseItems(gil);
return;
}
/* itemInList
see if a gopher item is in an item list */
BOOLEAN
itemInList(list, item)
gopherItemListP list;
gopherItemP item;
{
gopherItemP p;
BOOLEAN same;
if (list == NULL || item == NULL) return FALSE;
for (p = list->first; (p != item && p != NULL); p=p->next) {
same = compareItem(item, p);
if (same) break;
}
return (p != NULL);
}
#ifdef DEBUG_LIST
/* printItemList
Print a list of gopher items for checking the list contents */
void
printItemList(list, label)
gopherItemListP list;
char *label;
{
gopherItemP gi;
int i;
if (list == NULL) fprintf(stdout, "NULL list %s\n", label);
else {
gi = list->first;
fprintf (stdout, "list %s:\n", label);
while (gi != NULL) {
fprintf (stdout, "\t(");
for (i=0; i<PREFIX_LEN; i++)
fprintf (stdout, " %d ",
(int)((USER_STRING_PREFIX(gi))[i]));
fprintf (stdout, ") ");
fprintf (stdout, "(%s)\n", USER_STRING(gi));
gi = gi->next;
}
fprintf (stdout, " end of list\n");
}
}
#endif /* DEBUG_LIST */